home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / C++ Grammar / c++grammar.sit / freegrm4.txt < prev    next >
Text File  |  1991-02-14  |  18KB  |  316 lines

  1. FILENAME: FREEGRAM4.TXT
  2. AUTHOR: Jim Roskind
  3.         Independent Consultant
  4.         516 Latania Palm Drive
  5.         Indialantic FL 32903
  6.         (407)729-4348
  7.         jar@ileaf.com
  8.         or ...uunet!leafusa!jar
  9.         
  10.  
  11.                                                         6/6/90
  12.  
  13. Dear C++ and C Grammar User,
  14.  
  15. I have written a YACC debugging tool, and a set of grammars for C and 
  16. C++ in order to use them within my own personal project  development.  
  17. I  have made my work in this area available to other developers at no 
  18. charge with the hope that they would use  my  work.   I  believe  the 
  19. entire  C++  community can benefit from such standardization.  If any 
  20. of the copyright notices on the grammars  (which  are  VERY  liberal) 
  21. prevent using my work, please notify me of the problem.
  22.  
  23. Note  that  the  grammars can each be processed by YACC, but they are 
  24. very clean, and make NO USE of the precedence setting  (i.e.:  %prec) 
  25. or  associativity  setting  (i.e.:%assoc)  constructs  of YACC.  This 
  26. feature should make them easily portable to  other  parser  generator 
  27. input  format.  This "cleanliness" fact also provides brutal exposure 
  28. of all the complex constructs in  C++,  and  the  complexity  of  the 
  29. grammar as a whole (the C++ grammar is 2 to 3 times as large as the C 
  30. grammar) reflects this exposure.
  31.  
  32. The files included in this set are:
  33.  
  34.     FREEGRM4.TXT    This introductory file
  35.     GRAMMAR4.TXT    Parsing ambiguities in C++, and in my grammar
  36.     CPP4.Y          My YACC compatible C++ grammar
  37.     C4.Y            My YACC compatible, ANSI C conformant grammar
  38.     CPP4.L          Flex input file defining a C++ lexical analyser
  39.     SKELGRPH.C      A hacked file from the Berkeley YACC distribution.
  40.  
  41. Aside from the addition of several files, this release of my  grammar 
  42. corrects  a  few  problems located in my prior release.  This release 
  43. will hopefully conclude compliance with C++  2.0,  and  allow  me  to 
  44. release a C++ 2.1 compliant grammar (re: nested types).
  45.  
  46. Since my first public release of my grammar, I have received a number 
  47. of requests.  One of the most  common  requests  was  for  a  lexical 
  48. analyser  to  go  with  the  grammar.   This  release  of the grammar 
  49. provides such a a "bare bones" lexical analyser.  The  analyser  does 
  50. not  support  preprocessing,  or  even comment removal.  In addition, 
  51. since I have not included a symbol table, or semantic actions in  the 
  52. grammar  to  maintain  proper  context (i.e., current scope), typedef 
  53. names and struct/class/union/enum tags are not *really* defined.   To 
  54. allow  users to experiment with my grammar without a symbol table, my 
  55. lexer assumes that if the first letter of the  name  is  upper  case, 
  56. then  then name is a type name.  This hack is far from sufficient for 
  57. parsing full blown programs, but  it  is  more  than  sufficient  for 
  58. experimenting  with  the  grammar to determine the acceptability of a 
  59. token sequence, and to understand how my grammar parsed the sequence.
  60.  
  61. Since I did not believe  that  a  lexical  analyser  alone  would  be 
  62. sufficient to assist many people with playing with my grammar, I have 
  63. also provided the basis for a tool  to  explain  what  a  grammar  is 
  64. doing.   Specifically, I have modified a file that is included in the 
  65. Berkeley YACC distribution so that parsers generated by such  a  YACC 
  66. would  automatically  display a syntax tree in graphical-ASCII format 
  67. during a parse.  The instructions for using and  building  this  yacc 
  68. tool  are  presented  in  the  next  section.  Note that there are no 
  69. significant special hooks in my grammar or parser to excite this yacc 
  70. tool,  and  the tool can be used equally well on any grammar that you 
  71. are working with.
  72.  
  73. I have posted all 6 files to comp.lang.c++, to make this  information 
  74. as  available  as possible to users and developers.  I will also post 
  75. this introductory note to  comp.compilers,  and  comp.lang.c.   I  am 
  76. arranging  for  archival  support  via several ftp sites, and updates 
  77. will be posted to those sites.  I will also try to get the source  to 
  78. Berkeley  YACC  posted  to  these ftp sites, although it is certainly 
  79. available at more central sites.
  80.  
  81.  
  82. HOW TO USE THE DISTRIBUTION FILES TO PLAY WITH THE C++ GRAMMAR
  83.  
  84. Note that  the  following  instructions  assume  that  you  have  the 
  85. Berkeley  YACC  source  on  hand.   You  can actually use any YACC to 
  86. process the grammar, but running the resulting  demo  (which  has  no 
  87. semantic  actions)  will  tend  to be quite boring.  If you can't get 
  88. hold of the Berkeley YACC, you should at  least  try  to  enable  the 
  89. "debugging options" in your parser to so that you can see in some way 
  90. what reductions are taking  place.  (Hint:  search  for  the  letters 
  91. "debug" in the C file that your yacc produces...).
  92.  
  93.         1) Get the entire source for Berkeley YACC 1.4 2/25/90
  94.         2) Verify that you can make the YACC
  95.         3) Rename SKELETON.C to SKELOLD.C, and implant my SKELGRPH.C
  96.                 in that directory as SKELETON.C
  97.         4) Make the yacc using this new SKELETON.C
  98.         5) Using the above yacc, process my CPP4.Y file
  99.                 yacc -dvl cpp4.y
  100.            The result should be a file y.tab.c, and y.tab.h
  101.         6) Using Flex (replacement for lex) process my CPP4.L file
  102.                 flex cpp4.l
  103.            the result should be yy.lex.c
  104.         7) Compile the two files
  105.                 cc -o cpp4  y.tab.c yy.lex.c
  106.            the result should be an executable called cpp4
  107.         8) Set the environment variable YYDEBUG to 6
  108.                 setenv YYDEBUG 6
  109.            If you don't do this, the graphical output will not appear!
  110.         9) Run the program cpp4
  111.                 cpp4
  112.         10) Try the input:
  113.                 int a;
  114.         11) You should see a nice parse tree.  Enjoy.  Note that
  115.             the lexer DOES NOT INCLUDE A SYMBOL TABLE, and does
  116.             NOT KEEP TRACK OF CURRENT SCOPES.  The hack (see the
  117.             CPP4.L file for details) is to assume that any identifier
  118.             that begins with a capital letter is a typedef name
  119.             Send complaints about code that doesn't parse "correctly".
  120.  
  121.  
  122. INTRODUCTION TO 3/3/90 Version of my release
  123.  
  124. In   light   of   the   recent  debate  on  comp.lang.c++  about  the 
  125. "impossibility" of generating a YACC grammar for  C++  (that  doesn't 
  126. also  accept  every  possible  string  of  tokens),  providing  these 
  127. grammars at this point is especially nice.   Rather  than  addressing 
  128. each of the ad hoc arguments that such an endeavor is impossible (the 
  129. least convincing  of  which  said  effectively:  "...  heard  it  was 
  130. impossible,  ...  something  about LALR ...", and the most correct of 
  131. which said: "...it is not possible to create a  simple  YACC  grammar 
  132. for  C++.."),  I  am  offering  my  grammars  as  my  rather complete 
  133. commentary on the topic. (I'll probably get some flaming due to  this 
  134. comment,  but  I had to read all the stuff that was posted, that told 
  135. me what I had done was impossible. ;-) ) My general feeling  is  that 
  136. it  is  a  shame  for  opinions  to  be  confused with facts, and for 
  137. impossibility to be confused with difficulty or complexity.
  138.  
  139. Developing the C grammar (that is intended to be compatible with  the 
  140. ANSI C standard) was relatively straight forward (compared to the C++ 
  141. grammar).  The one difficulty in this process was the desire to avoid 
  142. use  of  %prec  and  %assoc  constructs  in YACC, which would tend to 
  143. obscure ambiguities.  Since I didn't know what ambiguities were lying 
  144. in  wait  in  C++,  obscuring  ambiguities was unacceptable.  It took 
  145. several weeks to remove the conflicts that typically appear, and  the 
  146. tedious  process  exposed  several ambiguities that are not currently 
  147. disambiguated by the ANSI standard.  The quality of the C grammar  is 
  148. (IMHO)  dramatically  higher than what has been made available within 
  149. the  public  domain.   Specifically,  a  C   grammar's   support   of 
  150. redefinition of typedef names within inner scopes (the most difficult 
  151. area of  the  grammar)  is  typically  excluded  from  public  domain 
  152. grammar,  and  even  excluded  from  most  grammars that are supplied 
  153. commercially with parser generators!  I expect that this grammar will 
  154. be very useful in the development of C related tools.
  155.  
  156. The development of the C++ grammar (initially compatible with version 
  157. 1.2, but enhanced to support version 2.0 specifications as they  were 
  158. made  available)  was anything but straight forward.  The requirement 
  159. that I set to NOT USE %prec and %assoc proved both a blessing  and  a 
  160. curse.   The  blessing was that I could see what the problems were in 
  161. the language, the curse was that there were A LOT of conflicts (I can 
  162. recall  times  during  the  development  effort  when  the  number of 
  163. conflicts was well in excess of 200).  Initially I was  unaware  that 
  164. many  other  attempts  had  been  made  and  failed, and I went ahead 
  165. "blindly" trying to resolve  the  conflicts  in  my  grammar.   After 
  166. raising  the  issues  that I noticed with Bjarne Stroustrup, I became 
  167. aware that there were some very significant  syntactical  ambiguities 
  168. within  the  current  C++ language.  Fortunately, by the time I first 
  169. spoke to Dr. Stroustrup, I had  already  derived  some  results  that 
  170. other  attempts  had  not  uncovered.   Encouraged  by  my results, I 
  171. continued on despite hearing ever louder  claims  that  my  goal  was 
  172. "impossible".
  173.  
  174. Towards  the  end  of  the development of the C++ grammar, which took 
  175. roughly 3 months of my time, I began to see the folly in part  of  my 
  176. quest.   I  came to the conclusion that further attempts to modify my 
  177. grammar, so as to defer resolutions of ambiguities, would lead to  an 
  178. unreadable language. Specifically, my feeling was that I was entering 
  179. into a battle of  wits  with  the  compiler,  and  the  compiler  was 
  180. starting  to  win.   It  was beginning to be the case that the parser 
  181. COULD figure out what I said, but I couldn't.  Indeed, even  examples 
  182. in  a  version  of  the  C++  2.0  reference manual demonstrated this 
  183. problem (my parser could parse some examples that neither I  nor  the 
  184. authors parsed correctly!).  At this point I decided to stop my quest 
  185. to FURTHER defer resolutions of  ambiguities,  and  let  the  grammar 
  186. commit  in  one  direction  (always in favor of declarations), at the 
  187. late point that is provided by my grammar.  If this direction  proved 
  188. "incorrect in light of the context that followed", then I generated a 
  189. syntax error.  I  believe  this  strategy  provides  ample  room  for 
  190. expressiveness.  In  support of this expressiveness, I have (based on 
  191. my discussions with language  experts)  deferred  disambiguation  far 
  192. longer  than  other  attempts at producing an LR(1) grammar.  I would 
  193. strongly argue that any code that my grammar identifies as  having  a 
  194. "syntax  error"  (based  on  "premature"  disambiguation), but cfront 
  195. allows, should ABSOLUTELY be rewritten in a less ambiguous (and hence 
  196. more portable) form.  As a final comment, by virtue of the consistent 
  197. methodology used to build my grammar, there are a number  of  clearly 
  198. unambiguous  constructs  that  my  grammar  CAN parse, and cfront 2.0 
  199. cannot (not to mention recent versions of GNU's G++ and Zortech's C++ 
  200. compiler).
  201.  
  202. One  major  motivation for using the C++ grammar that I have provided 
  203. is that it is capable of supporting old  style  function  definitions 
  204. (e.g.:  main(argc,  argv)  int  argc;  char*argv[];  {...}  ).  To my 
  205. knowledge, no other C++ parser is currently capable of this  feat.  I 
  206. believe  this  capability  was  removed from the C++ specification in 
  207. order to reduce ambiguities in a specific implementation (cfront). As 
  208. my  grammar  demonstrates,  this action was not necessary. Supporting 
  209. old style function definition GREATLY eases the transition to the use 
  210. of  C++  from  traditional C.  I expect that as some parsers begin to 
  211. support this option, that other parsing engines  will  be  forced  in 
  212. this  direction  by a competitive marketplace.  Using my grammar, and 
  213. the standards it  implies,  appears  to  be  a  very  straightforward 
  214. approach to this support.
  215.  
  216. A  second motivation for using my grammar is that it can be processed 
  217. by YACC.  The advantage in this fact lies with YACC's  capability  to 
  218. identify  ambiguities.   For  software manufacturers that are heavily 
  219. concerned with correctness, this  is  an  INCREDIBLE  advantage.   My 
  220. experience  with  hand  written  parsers  (which  usually represent a 
  221. translation by a fallible human from a grammar to  parsing  code)  is 
  222. that  they evolve and become more correct with time.  Ambiguous cases 
  223. are often misparsed, without the author ever realizing  there  was  a 
  224. conflict!  In  contrast,  either  a  YACC  grammar  supports  a given 
  225. construct, or it doesn't.  If a YACC grammar  supports  a  construct, 
  226. the  semantic interpretation is usually rather straight forward.  The 
  227. likelihood  of  internal  errors   in   the   parser   is   therefore 
  228. SIGNIFICANTLY  reduced. The fact the the grammars I supplied are free 
  229. of %assoc  and  %prec  operators,  implies  the  grammar  are  fairly 
  230. portable,  and  the  conflicts  are open to peer code review (and not 
  231. obscured).
  232.  
  233. If you find any errors in my grammars, I would be DELIGHTED  to  hear 
  234. mention  of  them!!!!   These  should  fall into one of the following 
  235. categories:
  236.  
  237.         1) The grammar left out the following features of C++...
  238.         or
  239.         2) The grammar mis-parses the following sequences...
  240.         or
  241.         3) The discussion of the following ambiguity is
  242.         incorrect...
  243.         4) The grammar could be simplified as follows...
  244.  
  245. Please send correspondence of this form to jar@ileaf.com. My response 
  246. to  1's  will  be  to add the feature (if possible!); feel sad that I 
  247. made a mistake; and feel glad that YOU  found  it.   I  will  have  a 
  248. similar  response  to  2's.   Responses  of  type  3 are GREAT, but I 
  249. haven't found many folks that really get into YACC ambiguities, so  I 
  250. have  low expectations... feel free to surprise me!!! :-) :-).  Items 
  251. of type 3 are interesting, but since simplicity is in the eye of  the 
  252. beholder,  such  suggestions  are  subject  to  debate.   I  would be 
  253. interested in seeing suggestions in this  area  with  the  constraint 
  254. that  they  do  not  increase the number of conflicts in the grammar!  
  255. Please use YACC to check your suggestions before submitting them. (It 
  256. is  often  AMAZING how the slightest change in the grammar can change 
  257. the number of conflicts, and it took a great deal of  work  to  reach 
  258. the current state). Distribution site(s) will be set up to distribute 
  259. updates  and  or  corrections.   Postings  about  the   presence   of 
  260. corrections will be made on the net.
  261.  
  262. Since  the  two  grammars (C and C++) were generated in parallel, you 
  263. should  be  able  to  compare  non-terminals  directly.   This   will 
  264. hopefully  make  it easier to identify the complexities involved with 
  265. the C++ grammar, and "ignore" those that result from standard ANSI C. 
  266. In  both  cases I have left the standard if-if-else ambiguity intact. 
  267. In the case of ANSI C grammar, this is the only shift-reduce conflict 
  268. in  the grammar.  Although there are a number of conflicts in the C++ 
  269. grammar, there are actually very few classes of problems. In order to 
  270. disambiguate  the C++ grammar enough that YACC can figure out what to 
  271. do, I was commonly forced to "inline expand" non-terminals  found  in 
  272. the  C  grammar.  This expansion allowed YACC to defer disambiguation 
  273. until it was possible for an LR(1) parser to understand the  context. 
  274. The  unfortunate  consequence  of  this  inline  expansion is a large 
  275. growth in the number of rules,  and  the  presence  of  an  effective 
  276. "multiplier" in most cases where conflicts do occur. As a result, any 
  277. conflicts that arise are multiplied by a factor corresponding to  the 
  278. number  of  rules  I  had to list separately.  I have grouped the C++ 
  279. grammar conflicts in the "Status" section of the  GRAMMAR.TXT  paper, 
  280. but  you  are  welcome to explore my grammars using YACC directly (be 
  281. warned that you will need a robust version of YACC to handle the  C++ 
  282. sized  grammar).  PLEASE do not be put off by the number of conflicts 
  283. in the C++ grammar.  There are VERY FEW CONFLICTS, but my  elaborated 
  284. grammar confuses the count.
  285.  
  286. The  GRAMMAR4.TXT  paper is FAR from a publishable quality paper, but 
  287. it discusses many  of  the  issues  involved  in  ambiguities  in  my 
  288. grammar,  and more generally in the C++ language. I hope GRAMMAR4.TXT 
  289. it is a vast improvement over "nothing  at  all",  but  apologize  in 
  290. advance  for  lack  of  polished  structure, and the presence of many 
  291. typos  (which  must  surely  be  present).  I  hope  you  find   this 
  292. almost-paper  interesting.  My attempts at documenting conflicts have 
  293. certainly clarified the problems in my mind. Based on  my  experience 
  294. with  the  conflicts  I  have  identified, most current compilers and 
  295. translator fall prey to the situations that I have uncovered.  I hope 
  296. that other compilers, that do not make use of the grammar I have made 
  297. available, will at least seek to standardize the  resolution  of  the 
  298. problems identified.
  299.  
  300. As  a  small commercial message... I am a freelance consultant, and I 
  301. travel far and wide to perform contracts.  If you like the work  that 
  302. I  am  presenting in this group of documents, and would like to see a 
  303. resume or at least talk, please feel free to contact me.
  304.  
  305. I hope that the grammars that I have  provided,  will  lead  to  many 
  306. successful C++ processing projects.
  307.  
  308. Jim Roskind
  309. Independent Consultant
  310. 516 Latania Palm Drive
  311. Indialantic FL 32903
  312. (407)729-4348
  313. jar@ileaf.com
  314. or ...!uunet!leafusa!jar
  315.  
  316.